---
--- api 黑名单限流脚本(改良)
--- Created by ZhuHJay.
--- DateTime: 2023/3/20 10:25
---
local limitKey = KEYS[1]
local noticeKey = KEYS[2]
local blackKey = KEYS[3]
local limit = tonumber(ARGV[1])
local expire = tonumber(ARGV[2])
local notice = tonumber(ARGV[3])
local noticeExpire = tonumber(ARGV[4])
local target = ARGV[5]

-- 首先判断是否存在黑名单中
local blackCache = redis.call('SISMEMBER', blackKey, target)
if (blackCache == 1) then
    return -1
end

-- 判断限流
local limitCache = redis.call('GET', limitKey)
if (not limitCache) then
    redis.call('SETEX', limitKey, expire, 1)
    return 1
end

-- 有限流缓存计数
if (tonumber(limitCache) < limit) then
    return redis.call('INCR', limitKey)
end

-- 达到限流次数 -> 限流通知计数
local noticeCache = redis.call('GET', noticeKey)
if (not noticeCache) then
    redis.call('SETEX', noticeKey, noticeExpire, 1)
    return 0
end

-- 限流通知计数到达阈值
if (tonumber(noticeCache) >= notice) then
    redis.call('SADD', blackKey, target)
    -- 不再需要限流通知计数
    redis.call('DEL', noticeKey)
    return limit + notice
end

-- 限流通知计数增长
redis.call('INCR', noticeKey)
return 0